with System;
with FT2.Types; use FT2.Types;
with FT2.Image; use FT2.Image;

package FT2.Base is

   pragma Elaborate_Body;

   type FT_Face_Flag is new FT_ULong;
   FT_FACE_FLAG_SCALABLE          : constant FT_Face_Flag :=    16#1#;
   FT_FACE_FLAG_FIXED_SIZES       : constant FT_Face_Flag :=    16#2#;
   FT_FACE_FLAG_FIXED_WIDTH       : constant FT_Face_Flag :=    16#4#;
   FT_FACE_FLAG_SFNT              : constant FT_Face_Flag :=    16#8#;
   FT_FACE_FLAG_HORIZONTAL        : constant FT_Face_Flag :=   16#10#;
   FT_FACE_FLAG_VERTICAL          : constant FT_Face_Flag :=   16#20#;
   FT_FACE_FLAG_KERNING           : constant FT_Face_Flag :=   16#40#;
   FT_FACE_FLAG_FAST_GLYPHS       : constant FT_Face_Flag :=   16#80#;
   FT_FACE_FLAG_MULTIPLE_MASTERS  : constant FT_Face_Flag :=  16#100#;
   FT_FACE_FLAG_GLYPH_NAMES       : constant FT_Face_Flag :=  16#200#;
   FT_FACE_FLAG_EXTERNAL_STREAM   : constant FT_Face_Flag :=  16#400#;
   FT_FACE_FLAG_HINTER            : constant FT_Face_Flag :=  16#800#;
   FT_FACE_FLAG_CID_KEYED         : constant FT_Face_Flag := 16#1000#;
   FT_FACE_FLAG_TRICKY            : constant FT_Face_Flag := 16#2000#;

   type FT_Style_Flag is new FT_ULong;
   FT_STYLE_FLAG_ITALIC : constant FT_Style_Flag := 16#1#;
   FT_STYLE_FLAG_BOLD   : constant FT_Style_Flag := 16#2#;

--     type FT_Open_Flag is new FT_UInt;
--     FT_OPEN_MEMORY   : constant FT_Open_Flag := 16#1#;
--     FT_OPEN_STREAM   : constant FT_Open_Flag := 16#2#;
--     FT_OPEN_PATHNAME : constant FT_Open_Flag := 16#4#;
--     FT_OPEN_DRIVER   : constant FT_Open_Flag := 16#8#;
--     FT_OPEN_PARAMS   : constant FT_Open_Flag := 16#10#;

   -- One should create two types here, one for load flags (16 bits) and an enum
   -- for load target (16 bits)
   type FT_Load_Flags is new FT_UInt;
   FT_LOAD_DEFAULT                     : constant FT_Load_Flags :=    16#0#;
   FT_LOAD_NO_SCALE                    : constant FT_Load_Flags :=    16#1#;
   FT_LOAD_NO_HINTING                  : constant FT_Load_Flags :=    16#2#;
   FT_LOAD_RENDER                      : constant FT_Load_Flags :=    16#4#;
   FT_LOAD_NO_BITMAP                   : constant FT_Load_Flags :=    16#8#;
   FT_LOAD_VERTICAL_LAYOUT             : constant FT_Load_Flags :=   16#10#;
   FT_LOAD_FORCE_AUTOHINT              : constant FT_Load_Flags :=   16#20#;
   FT_LOAD_CROP_BITMAP                 : constant FT_Load_Flags :=   16#40#;
   FT_LOAD_PEDANTIC                    : constant FT_Load_Flags :=   16#80#;
   FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH : constant FT_Load_Flags :=  16#200#;
   FT_LOAD_NO_RECURSE                  : constant FT_Load_Flags :=  16#400#;
   FT_LOAD_IGNORE_TRANSFORM            : constant FT_Load_Flags :=  16#800#;
   FT_LOAD_MONOCHROME                  : constant FT_Load_Flags := 16#1000#;
   FT_LOAD_LINEAR_DESIGN               : constant FT_Load_Flags := 16#2000#;
   FT_LOAD_NO_AUTOHINT                 : constant FT_Load_Flags := 16#8000#;

   FT_LOAD_TARGET_NORMAL : constant FT_Load_Flags := 16#00000#;
   FT_LOAD_TARGET_LIGHT  : constant FT_Load_Flags := 16#10000#;
   FT_LOAD_TARGET_MONO   : constant FT_Load_Flags := 16#20000#;
   FT_LOAD_TARGET_LCD    : constant FT_Load_Flags := 16#30000#;
   FT_LOAD_TARGET_LCD_V  : constant FT_Load_Flags := 16#40000#;

   --  function FT_LOAD_TARGET_MODE (x : FT_Load_Flags) return FT_Render_Mode;

   type FT_SubGlyph_Flags is new FT_UInt;
   FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS     : constant FT_SubGlyph_Flags :=   16#1#;
   FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES : constant FT_SubGlyph_Flags :=   16#2#;
   FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID   : constant FT_SubGlyph_Flags :=   16#4#;
   FT_SUBGLYPH_FLAG_SCALE              : constant FT_SubGlyph_Flags :=   16#8#;
   FT_SUBGLYPH_FLAG_XY_SCALE           : constant FT_SubGlyph_Flags :=  16#40#;
   FT_SUBGLYPH_FLAG_2X2                : constant FT_SubGlyph_Flags :=  16#80#;
   FT_SUBGLYPH_FLAG_USE_MY_METRICS     : constant FT_SubGlyph_Flags := 16#200#;


   -- Base types

   type FT_Glyph_Metrics is record
      Width                : FT_Pos;
      Height               : FT_Pos;
      Horizontal_Bearing_X : FT_Pos;
      Horizontal_Bearing_Y : FT_Pos;
      Horizontal_Advance   : FT_Pos;
      Vertical_Bearing_X   : FT_Pos;
      Vertical_Bearing_Y   : FT_Pos;
      Vertical_Advance     : FT_Pos;
   end record;
   pragma Convention (C, FT_Glyph_Metrics);

   type FT_Bitmap_Size is record
      Height : FT_Short;
      Width  : FT_Short;
      Size   : FT_Pos;
      X_ppem : FT_Pos;
      Y_ppem : FT_Pos;
   end record;
   pragma Convention (C, FT_Bitmap_Size);

   type FT_Bitmap_Sizes_Ptr is private; --access all FT_Bitmap_Size;
   type FT_Bitmap_Size_Array is array (Natural range <>) of aliased FT_Bitmap_Size;
   function To_Array
     (Ptr : FT_Bitmap_Sizes_Ptr;
      Length : FT_Int)
      return FT_Bitmap_Size_Array;

   type FT_Library is access Void;
   pragma Convention (C, FT_Library);


   -- FT_Module
   -- FT_Driver
   -- FT_Renderer

   type FT_FaceRec;
   type FT_Face is access FT_FaceRec;
   pragma Convention (C, FT_Face);

   type FT_SizeRec;
   type FT_Size is access FT_SizeRec;
   pragma Convention (C, FT_Size);

   type FT_GlyphSlotRec;
   type FT_GlyphSlot is access FT_GlyphSlotRec;
   pragma Convention (C, FT_GlyphSlot);

   type FT_CharMapRec;
   type FT_CharMap is access FT_CharMapRec;
   pragma Convention (C, FT_CharMap);

   type FT_Charmaps_Ptr is private;
   type FT_CharMap_Array is array (Natural range <>) of aliased FT_CharMap;
   function To_Array
     (Ptr : FT_Charmaps_Ptr;
      Length : FT_Int)
      return FT_CharMap_Array;

   --  This is declared as an enum in FT2, but it is said that some encodings
   --  could be defined by specific drivers. Therefore, this is not an
   --  enumeration (Ada meaning).
   type FT_Encoding is new FT_Int;
   FT_ENCODING_NONE : constant FT_Encoding := 0;
   FT_ENCODING_MS_SYMBOL : constant FT_Encoding :=
     C'Pos ('s') * 2**24 + C'Pos ('y') * 2**16 + C'Pos ('m') * 2**8 + C'Pos ('b');
   FT_ENCODING_UNICODE : constant FT_Encoding :=
     C'Pos ('u') * 2**24 + C'Pos ('n') * 2**16 + C'Pos ('i') * 2**8 + C'Pos ('c');
   FT_ENCODING_SJIS : constant FT_Encoding :=
     C'Pos ('s') * 2**24 + C'Pos ('j') * 2**16 + C'Pos ('i') * 2**8 + C'Pos ('s');
   FT_ENCODING_GB2312 : constant FT_Encoding :=
     C'Pos ('g') * 2**24 + C'Pos ('b') * 2**16 + C'Pos (' ') * 2**8 + C'Pos (' ');
   FT_ENCODING_BIG5 : constant FT_Encoding :=
     C'Pos ('b') * 2**24 + C'Pos ('i') * 2**16 + C'Pos ('g') * 2**8 + C'Pos ('5');
   FT_ENCODING_WANSUNG : constant FT_Encoding :=
     C'Pos ('w') * 2**24 + C'Pos ('a') * 2**16 + C'Pos ('n') * 2**8 + C'Pos ('s');
   FT_ENCODING_JOHAB : constant FT_Encoding :=
     C'Pos ('j') * 2**24 + C'Pos ('o') * 2**16 + C'Pos ('h') * 2**8 + C'Pos ('a');
   FT_ENCODING_ADOBE_STANDARD : constant FT_Encoding :=
     C'Pos ('A') * 2**24 + C'Pos ('D') * 2**16 + C'Pos ('O') * 2**8 + C'Pos ('B');
   FT_ENCODING_ADOBE_EXPERT : constant FT_Encoding :=
     C'Pos ('A') * 2**24 + C'Pos ('D') * 2**16 + C'Pos ('B') * 2**8 + C'Pos ('E');
   FT_ENCODING_ADOBE_CUSTOM : constant FT_Encoding :=
     C'Pos ('A') * 2**24 + C'Pos ('D') * 2**16 + C'Pos ('B') * 2**8 + C'Pos ('C');
   FT_ENCODING_ADOBE_LATIN_1 : constant FT_Encoding :=
     C'Pos ('l') * 2**24 + C'Pos ('a') * 2**16 + C'Pos ('t') * 2**8 + C'Pos ('1');
   FT_ENCODING_OLD_LATIN_2 : constant FT_Encoding :=
     C'Pos ('l') * 2**24 + C'Pos ('a') * 2**16 + C'Pos ('t') * 2**8 + C'Pos ('2');
   FT_ENCODING_APPLE_ROMAN : constant FT_Encoding :=
     C'Pos ('a') * 2**24 + C'Pos ('r') * 2**16 + C'Pos ('m') * 2**8 + C'Pos ('n');

   type FT_CharMapRec is record
      Face        : FT_Face;
      Encoding    : FT_Encoding;
      Platform_Id : FT_UShort;
      Encoding_Id : FT_UShort;
   end record;

   -- FT_Face_Internal

   -------------
   -- FaceRec --
   -------------

   type FT_FaceRec is record
      Num_Faces           : FT_Long;
      Face_Index          : FT_Long;
      Face_Flags          : FT_Face_Flag;
      Style_Flags         : FT_Style_Flag;
      Num_Glyphs          : FT_Long;
      Family_Name         : FT_String_Ptr;
      Style_Name          : FT_String_Ptr;
      Num_Fixed_Sizes     : FT_Int;
      Available_Sizes     : FT_Bitmap_Sizes_Ptr;
      Num_Charmaps        : FT_Int;
      Charmaps            : FT_Charmaps_Ptr;
      User                : FT_Generic;

      -- The following member variables (down to 'underline_thickness')
      -- are only relevant to scalable outlines;
      -- Cf. FT_Bitmap_Size for bitmap fonts.
      BBox                : FT_BBox;
      Units_Per_EM        : FT_UShort;
      Ascender            : FT_Short;
      Descender           : FT_Short;
      Height              : FT_Short;
      Max_Advance_Width   : FT_Short;
      Max_Advance_Height  : FT_Short;
      Underline_Position  : FT_Short;
      Underline_Thickness : FT_Short;

      Glyph               : FT_GlyphSlot;
      Size                : FT_Size;
      Charmap             : FT_CharMap;
      -- Other fields exist but are not represented here
   end record;
   pragma Convention (C, FT_FaceRec);


   function Get_Charmaps (Face : FT_Face) return FT_CharMap_Array;

   -- FT_Size_Internal

   type FT_Size_Metrics is record
      X_ppem      : FT_UShort;
      Y_ppem      : FT_UShort;
      X_Scale     : FT_Fixed;
      Y_Scale     : FT_Fixed;
      Ascender    : FT_Pos;
      Descender   : FT_Pos;
      Height      : FT_Pos;
      Max_Advance : FT_Pos;
   end record;
   pragma Convention (C, FT_Size_Metrics);

   -------------
   -- SizeRec --
   -------------

   type FT_SizeRec is record
      Face     : FT_Face;
      User     : FT_Generic;
      Metrics  : FT_Size_Metrics;
--      Internal : FT_Size_Internal;
   end record;
   pragma Convention (C, FT_SizeRec);

   type FT_SubGlyph is access Void;


   -- FT_Slot_Internal;

   ------------------
   -- GlyphSlotRec --
   ------------------

   type FT_GlyphSlotRec is record
      Library             : FT_Library;
      Face                : FT_Face;
      Next                : FT_GlyphSlot;
      Reserved            : FT_UInt;
      User                : FT_Generic;
      Metrics             : FT_Glyph_Metrics;
      Linear_Hori_Advance : FT_Fixed;
      Linear_Vert_Advance : FT_Fixed;
      Advance             : FT_Vector;
      Format              : FT_Glyph_Format;
      Bitmap              : FT_Bitmap;
      Bitmap_Left         : FT_Int;
      Bitmap_Top          : FT_Int;
      Outline             : FT_Outline;
      Num_SubGlyphs       : FT_UInt;
      SubGlyphs           : FT_SubGlyph; --###
      Control_Data        : System.Address;
      Control_Len         : FT_Long;
      LSB_Delta           : FT_Pos;
      RSB_Delta           : FT_Pos;
      Other               : System.Address;
--      Internal            : FT_Slot_Internal;
   end record;
   pragma Convention (C, FT_GlyphSlotRec);


   -------------
   -- Library --
   -------------

   procedure Init_FreeType
     (Library : in out FT_Library;
      Error : out FT_Error);

   procedure Done_FreeType
     (Library : in out FT_Library;
      Error : out FT_Error);

   -- FT_Parameter
--     type FT_Open_Args is record
--        Flags       : FT_Open_Flag := 0;
--        Memory_Base : FT_Bytes_Ptr; -- const
--        Memory_Size : FT_Long := 0;
--        Pathname    : FT_String_Ptr;
--        Stream      : FT_Stream;
--        Driver      : FT_Module;
--        Num_Params  : FT_Int := 0;
--        Params      : FT_Parameters_Ptr;
--     end record;

   procedure New_Face
     (Library : FT_Library;
      File_Path_Name : String;
      Face_Index : FT_Long;
      Face : in out FT_Face;
      Error : out FT_Error);

   procedure New_Memory_Face
     (Library : FT_Library;
      File_Base : System.Address;
      File_Size : FT_Long;
      Face_Index : FT_Long;
      Face : in out FT_Face;
      Error : out FT_Error);

--     procedure Open_Face
--       (Library : FT_Library;
--        Args : FT_Open_Args;
--        Face_Index : FT_Long;
--        Face : in out FT_Face);

   procedure Attach_File
     (Face : FT_Face;
      File_Path_Name : String;
      Error : out FT_Error);

--     procedure Attach_Stream
--       (Face : FT_Face;
--        Parameters : FT_Open_Args; -- in out ???
--        Error : out FT_Error);

   procedure Done_Face
     (Face : in out FT_Face;
      Error : out FT_Error);

   procedure Select_Size
     (Face : FT_Face;
      Strike_Index : FT_Int;
      Error : out FT_Error);


   type FT_Size_Request_Type is
     (FT_SIZE_REQUEST_TYPE_NOMINAL,
      FT_SIZE_REQUEST_TYPE_REAL_DIM,
      FT_SIZE_REQUEST_TYPE_BBOX,
      FT_SIZE_REQUEST_TYPE_CELL,
      FT_SIZE_REQUEST_TYPE_SCALES);
   pragma Convention (C, FT_Size_Request_Type);

   type FT_Size_RequestRec is record
      CType : FT_Size_Request_Type;
      Width : FT_Long;
      Height : FT_Long;
      Hori_Resolution : FT_UInt;
      Vert_Resolution : FT_UInt;
   end record;
   pragma Convention (C, FT_Size_RequestRec);

   -- FT_Size_Request

   procedure Request_Size
     (Face : FT_Face;
      Req : out FT_Size_RequestRec; -- pointer ?
      Error : out FT_Error);

   procedure Set_Char_Size
     (Face : FT_Face;
      Char_Width : FT_F26Dot6;
      Char_Height :  FT_F26Dot6;
      Horz_Resolution : FT_UInt;
      Vert_Resolution : FT_UInt;
      Error : out FT_Error);

   procedure Set_Pixel_Sizes
     (Face : FT_Face;
      Pixel_Width : FT_UInt;
      Pixel_Height : FT_UInt;
      Error : out FT_Error);

   procedure Load_Glyph
     (Face : FT_Face;
      Glyph_Index : FT_UInt;
      Load_Flags : FT_Load_Flags;
      Error : out FT_Error);

   procedure Load_Char
     (Face : FT_Face;
      Char_Code : FT_ULong;
      Load_Flags : FT_Load_Flags;
      Error : out FT_Error);

   procedure Set_Transform
     (Face : FT_Face;
      Matrix : FT_Matrix;
      Vector : FT_Vector);
   procedure Set_Transform
     (Face : FT_Face;
      Matrix : FT_Matrix);
   procedure Set_Transform
     (Face : FT_Face;
      Vector : FT_Vector);

   type FT_Render_Mode is
     (FT_RENDER_MODE_NORMAL,
      FT_RENDER_MODE_LIGHT,
      FT_RENDER_MODE_MONO,
      FT_RENDER_MODE_LCD,
      FT_RENDER_MODE_LCD_V);
   pragma Convention (C, FT_Render_Mode);

   procedure Render_Glyph
     (Slot : FT_GlyphSlot;
      Render_Mode : FT_Render_Mode;
      Error : out FT_Error);

   type FT_Kerning_Mode is
     (FT_KERNING_DEFAULT,
      FT_KERNING_UNFITTED,
      FT_KERNING_UNSCALED);
   pragma Convention (C, FT_Kerning_Mode);

   procedure Get_Kerning
     (Face : FT_Face;
      Left_Glyph : FT_UInt;
      Right_Glyph : FT_UInt;
      Kerning_Mode : FT_Kerning_Mode;
      Kerning : out FT_Vector;
      Error : out FT_Error);

   procedure Get_Track_Kerning
     (Face : FT_Face;
      Point_Size : FT_Fixed;
      Degree : FT_Int;
      Kerning : out FT_Fixed;
      Error : out FT_Error);

   procedure Get_Glyph_Name
     (Face : FT_Face;
      Glyph_Index : FT_UInt;
      Name : out String;
      Last : out Natural;
      Error : out FT_Error);

   function Get_Postscript_Name (Face : FT_Face) return String;

   procedure Select_Charmap
     (Face : FT_Face;
      Encoding : FT_Encoding;
      Error : out FT_Error);

   procedure Set_Charmap
     (Face : FT_Face;
      Charmap : FT_CharMap;
      Error : out FT_Error);

   function Get_Charmap_Index (Charmap : FT_CharMap) return FT_Int;

   function Get_Char_Index
     (Face : FT_Face;
      Char_Code : FT_ULong)
      return FT_UInt;

   procedure Get_First_Char
     (Face : FT_Face;
      First_Glyph_Index : out FT_UInt;
      First_Char_Code : out  FT_ULong);

   procedure Get_Next_Char
     (Face : FT_Face;
      Starting_Char_Code : FT_ULong;
      Next_Glyph_Index : out FT_UInt;
      Next_Char_Code : out FT_ULong);

   function Get_Name_Index
     (Face : FT_Face;
      Glyph_Name : String)
      return FT_UInt;

   procedure Get_SubGlyph_Info
     (Glyph : FT_GlyphSlot;
      Sub_Index : FT_UInt;
      Index : out FT_Int;
      Flags : out FT_SubGlyph_Flags;
      Arg1 : out FT_Int;
      Arg2 : out FT_Int;
      Transform : out FT_Matrix;
      Error : out FT_Error);

   type FT_FSType_Flags is new FT_UShort;
   FT_FSTYPE_INSTALLABLE_EMBEDDING        : constant FT_FSType_Flags := 16#0000#;
   FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING : constant FT_FSType_Flags := 16#0002#;
   FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING  : constant FT_FSType_Flags := 16#0004#;
   FT_FSTYPE_EDITABLE_EMBEDDING           : constant FT_FSType_Flags := 16#0008#;
   FT_FSTYPE_NO_SUBSETTING                : constant FT_FSType_Flags := 16#0100#;
   FT_FSTYPE_BITMAP_EMBEDDING_ONLY        : constant FT_FSType_Flags := 16#0200#;

   function Get_FSType_Flags (Face : FT_Face) return FT_FSType_Flags;

   function Get_Char_Variant_Index
     (Face : FT_Face;
      Char_Code : FT_ULong;
      Variant_Selector : FT_ULong)
      return FT_UInt;

   function Get_Char_Variant_Is_Default
     (Face : FT_Face;
      Char_Code : FT_ULong;
      Variant_Selector : FT_ULong)
      return FT_Int;

   function Get_Variant_Selectors
     (Face : FT_Face)
      return FT_UInt32_Array;

   function Get_Variants_Of_Char
     (Face : FT_Face;
      Char_Code : FT_ULong)
      return FT_UInt32_Array;

   function Get_Chars_Of_Variant
     (Face : FT_Face;
      Variant_Selector : FT_ULong)
      return FT_UInt32_Array;

   --function Mul_Div (A, B, C : FT_Long) return FT_Long;
   -- function Mul_Fix
   -- FT_DivFix
   -- FT_RoundFix
   -- FT_CeilFix
   -- FT_FloorFix
   -- FT_Vector_Transform

   procedure Library_Version
     (Library : FT_Library;
      Major : out FT_Int;
      Minor : out FT_Int;
      Patch : out FT_Int);

   function Check_TrueType_Patents
     (Face : FT_Face)
      return Boolean;

   procedure Set_Unpatented_Hinting
     (Face : FT_Face;
      Value : Boolean;
      Old_Value : out Boolean);

private
   type FT_Bitmap_Sizes_Ptr is access all FT_Bitmap_Size;
   pragma Convention (C, FT_Bitmap_Sizes_Ptr);

   type FT_Charmaps_Ptr is access all FT_CharMap;
   pragma Convention (C, FT_Charmaps_Ptr);

   pragma Import (C, Library_Version, "FT_Library_Version");
   pragma Import (C, Get_Charmap_Index, "FT_Get_Charmap_Index");
   pragma Import (C, Get_Char_Index, "FT_Get_Char_Index");
   pragma Import (C, Get_FSType_Flags, "FT_Get_FSType_Flags");
   pragma Import (C, Get_Char_Variant_Index, "FT_Get_Char_Variant_Index");
   pragma Import (C, Get_Char_Variant_Is_Default, "FT_Get_Char_Variant_Is_Default");

end FT2.Base;
